package com.acme.bankapp.service.bank;


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;

import com.acme.bankapp.domain.account.*;
import com.acme.bankapp.domain.bank.Bank;
import com.acme.bankapp.domain.client.*;
import com.acme.bankapp.service.exception.FileFormatException;

public class BankDataLoaderService {
	
	private static final String DEF_DELIT = "=;";
	private static final String KEY_ACC = "accounttype";
	private static final String KEY_BALANCE = "balance";
	private static final String KEY_OVER = "overdraft";
	private static final String KEY_NAME = "name";
	private static final String KEY_GENER = "gender";
	private static final String GENER_MALE = "m";
	private static final String GENER_FEMALE = "f";
	private static final String ACC_SAVE = "s";
	private static final String ACC_CHEK = "c";
	

	/**
	 * Loads a file which contains data feed in the following format: <br>
	 * accounttype=c|s;balance=100;overdraft=50;name=John;gender=m|f;
	 * 
	 * @param bank
	 * @param path
	 * @throws IOException 
	 */
	public void load(final Bank bank, final String path)  {
		BufferedReader bufferedReader = null;
		try {
			bufferedReader = new BufferedReader(new FileReader(path));
			readStrings(bank, bufferedReader);
		} catch (IOException e) {
			System.out.println(e.getMessage());
		} finally {
			try {
				bufferedReader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}
	
	private void readStrings(final Bank bank, BufferedReader br) throws IOException{
		String curstring;
		try {
			while ((curstring = br.readLine()) != null) {
				Client client = readNextClient(bank, curstring);
				BankApplication.addClient(bank, client);
			}
		} catch (FileFormatException e) {
			System.out.println(e.getMessage());
		}
	}
	
	private Client readNextClient(final Bank bank, String str) throws FileFormatException{
		
		String accType = null;
        double balance = 0;
        double overdraft = 0;
        AbstractAccount account = null;
        String clientname = null;
        Gender gender = Gender.MALE;
        
		StringTokenizer st = new StringTokenizer(str, BankDataLoaderService.DEF_DELIT);
		while (st.hasMoreTokens()) {

			switch (st.nextToken()) {

			case BankDataLoaderService.KEY_ACC:
				accType = readAccType(st.nextToken());
				break;

			case BankDataLoaderService.KEY_BALANCE:
				balance = readDouble(st.nextToken());
				break;
			case BankDataLoaderService.KEY_OVER:
				overdraft = readDouble(st.nextToken());
				break;
			case BankDataLoaderService.KEY_NAME:
				clientname = st.nextToken();
				break;
			case BankDataLoaderService.KEY_GENER:
				readGender(st.nextToken());
				break;

			default:
				throw new FileFormatException();
			}
		}
		
		if (accType == "checking") {
			account = new CheckingAccount(balance, overdraft);
		} else {
			account = new SavingsAccount(balance);
		}
			
		return 	new Client(clientname, gender, account);
	}
	
	private double readDouble(String str) throws FileFormatException {
		try {
			return Double.parseDouble(str);
		
		} catch (NumberFormatException nfe) {
			throw new FileFormatException("Double type error");
		}
	}

	private Gender readGender(String str) throws FileFormatException {
		switch (str) {
		case BankDataLoaderService.GENER_MALE:
			return Gender.MALE;
		case BankDataLoaderService.GENER_FEMALE:
			return Gender.FEMALE;
		default:
			throw new FileFormatException("Gender type error");
		}
	}

	private String readAccType(String str) throws FileFormatException {
		switch (str) {
		case BankDataLoaderService.ACC_CHEK:
			return "checking";
		case BankDataLoaderService.ACC_SAVE:
			return "saving";

		default:
			throw new FileFormatException("Account type error");
		}
	}

	

}
